#include "jeu.h"
#include <stdlib.h>
#include <time.h>


void jeuInit(plateauDeJeu& jeu, const char *niv)
{
	terrainInit(jeu.terrain, niv);
	srand(time(NULL));
	jeu.piece_courante = tire_numPiece();  // initialise la premiere piece, avec la premiere rotation
	jeu.rotation = 1;
	jeu.PosX = (TERRAIN_LG / 2) - 2;	// Le bloc fait 4x4.
	jeu.PosY = 0;
	jeu.piece_suivante = tire_numPiece();
	jeu.finJeu = false;
	jeu.Score.niveau = 0;
    jeu.Score.nbrScore = 0;
	jeu.Score.nbreLigne = 0;
}

Terrain jeuGetTerrain(const plateauDeJeu& jeu)
{
    return jeu.terrain;
}

//accesseurs et mutateurs sur les pieces (et leur rotations)
int jeuGetPiece_courante(const plateauDeJeu& jeu)
{
    return jeu.piece_courante;
}

void jeuSetPiece_courante(plateauDeJeu& jeu, int piece_suivante)
{
    jeu.piece_courante = jeu.piece_suivante;
    jeu.piece_suivante = tire_numPiece();
}

int jeuGetPiece_suivante(const plateauDeJeu& jeu)
{
    return jeu.piece_suivante;
}

int jeuGetRotation(const plateauDeJeu& jeu)
{
    return jeu.rotation;
}

void jeuSetRotation(plateauDeJeu & jeu, int R)
{
    jeu.rotation = (jeu.rotation + R)%4;      // modulo 4 car il y a 4 rotations possibles
}

//accesseurs et mutateurs sur les PosX et Pos Y

int jeuGetPosX(const plateauDeJeu& jeu)
{
    return jeu.PosX;
}
int jeuGetPosY(const plateauDeJeu& jeu)
{
    return jeu.PosY;
}
void jeuSetPosX(plateauDeJeu& jeu, int X)
{
    jeu.PosX = X;
}
void jeuSetPosY(plateauDeJeu& jeu, int Y)
{
    jeu.PosY = Y;
}

int Collision(const plateauDeJeu & jeu, int PosX, int PosY, int rotation )
{
	int x,y;
	for (x=0 ; x<=3 ; x++)
	{
		for(y=0 ; y<=3 ; y++)
		{
		    if (estOccupee(jeuGetPiece_courante(jeu), rotation, x , y)) // si la piece est differente de 0
            {
                if (terEstPositionPlaceValide(jeuGetTerrain(jeu), y+PosY, x+PosX) == false)
                {
                    return (1);
                }
            }
		}
    }
	return(0);// il n'y a pas de collision
}

void ajoutPiecePlateau(plateauDeJeu& jeu)
{
	int x,y;
	if(jeu.PosY <= 3)
	{
	    jeu.finJeu=true;
	}
	else
	{
	    jeu.finJeu=false;
	}
	for(x=0 ; x<=3 ; x++)
	{
		for(y=0 ; y<=3 ; y++)
		{
			if(SPiece[jeuGetPiece_courante(jeu)][jeuGetRotation(jeu)][4*y+x]!='0')
			{
				jeu.terrain.tableauPiecesPosees[jeuGetPosY(jeu)+y][jeuGetPosX(jeu)+x] = SPiece[jeuGetPiece_courante(jeu)][jeuGetRotation(jeu)][4*y+x];
			}
		}
    }
    LigneComplete(jeu);
    jeuSetPiece_courante(jeu,jeuGetPiece_suivante(jeu)); //change la piece courante, et crée la piece suivante
    jeuSetPosX(jeu, (TERRAIN_LG / 2) - 2);
    jeuSetPosY(jeu,0);
    jeuSetRotation(jeu,1);

}

void descentePiece(plateauDeJeu& jeu)
{
    if(Collision(jeu, jeuGetPosX(jeu), jeuGetPosY(jeu)+1, jeuGetRotation(jeu)) == 0)
    {
        jeuSetPosY(jeu,jeuGetPosY(jeu)+1);
    }
    else
    {
        ajoutPiecePlateau(jeu);
    }
}

void rotation(plateauDeJeu& jeu)
{
    int i ;
    int nombre = 0;
    int rotationSuivante = (jeuGetRotation(jeu)+1)%4;
    if (jeuGetPosX(jeu) == 8) // si la piece a une colonne de 0 a droite, avant la rotation
    {
        for(i=0 ; i<=3 ; i++)
        {
            if(SPiece[jeuGetPiece_courante(jeu)][rotationSuivante][3+4*i] == '0')//si il y a une ligne de 0
            {
                nombre++;
            }
        }
        if(nombre == 4)  // si la derniere colonne est que des 0, on fait la rotation a cet emplacement
        {
            jeuSetRotation(jeu, 1);
        }
        else  // sinon on se deplace d'un cran a gauche et on fait la rotation
        {
            jeuSetPosX(jeu, jeuGetPosX(jeu)-1);
            rotation(jeu);
        }
    }
    else if (jeuGetPosX(jeu) == 0 ) // si la piece a une colonne de 0 a gauche, avant la rotation
        {
            for(i=0 ; i<=3 ; i++)
            {
                if(SPiece[jeu.piece_courante][rotationSuivante][4*i] == '0')
                {
                    nombre++;
                }
            }
            if (nombre == 4 && Collision(jeu, jeuGetPosX(jeu) ,jeuGetPosY(jeu), rotationSuivante) == 0)  // si la premiere colonne est que des 0, on fait la rotation a cet emplacement
            {
                jeuSetRotation(jeu, 1);
            }
            else   // sinon on se deplace d'un cran a droite et on fait la rotation
            {
                jeuSetPosX(jeu, jeuGetPosX(jeu) + 1);
                rotation(jeu);
            }
        }
        else if(jeuGetPosX(jeu) == -1)
            {
                jeuSetPosX(jeu, jeuGetPosX(jeu) + 1);
                rotation(jeu);
            }
            else if (jeuGetPosX(jeu) == 9)
                {
                    jeuSetPosX(jeu, jeuGetPosX(jeu) - 1);
                    rotation(jeu);
                }
                else if(Collision(jeu, jeuGetPosX(jeu) ,jeuGetPosY(jeu), rotationSuivante) == 0)
                {
                    jeuSetRotation(jeu, 1);
                }
}


void jeuActionClavier(plateauDeJeu& jeu, const char touche)
{
	switch(touche)
	{
	    case 'g' :// la piece va sur la gauche
				if(Collision(jeu, jeuGetPosX(jeu)  -1, jeuGetPosY(jeu), jeuGetRotation(jeu))==0)
				{
					jeuSetPosX(jeu, jeuGetPosX(jeu) +-1);
				}
				break;
		case 'd' :// la piece va sur la droite
				if(Collision(jeu, jeuGetPosX(jeu)  + 1, jeuGetPosY(jeu), jeuGetRotation(jeu))==0)
				{
					jeuSetPosX(jeu, jeuGetPosX(jeu) +1);
				}
				break;
		case 'r' :// rotation de la piece
                rotation(jeu);
				break;
        case 's' : // la piece va jusqu'en bas d'un coup
				while(Collision(jeu, jeuGetPosX(jeu), jeuGetPosY(jeu)+1, jeuGetRotation(jeu)) == 0)
                {
                    jeuSetPosY(jeu,jeuGetPosY(jeu)+1);
                }
                ajoutPiecePlateau(jeu);
		case 't' : // la piece descend d'un cran
                if(Collision(jeu, jeuGetPosX(jeu), jeuGetPosY(jeu)+1, jeuGetRotation(jeu)) == 0)
                {
                    jeuSetPosY(jeu,jeuGetPosY(jeu)+1);
                }
                else
                {
                    ajoutPiecePlateau(jeu);
                }
				break;
        default : break;
	}
}


bool estLigneComplete(const plateauDeJeu & jeu, int Ligne) //on parcours le tableauPiecesPosées pour une certaine ligne, et on regarde si elle est complete
{
    int compteur = 0;
    int x;
	for(x=1 ; x < getDimX(jeu.terrain)-1 ; x++)
    {
		if (jeu.terrain.tableauPiecesPosees[Ligne][x] != '0')
		{
		    compteur++; //incremente le nombre de cases remplies par ligne
		}
	}
	if(compteur == getDimX(jeu.terrain)-2)
	{
        return true; // si toutes les cases de la lignes sont remplies
	}
	else
	{
	    return false;
	}
}

static void effacerLigne(plateauDeJeu & jeu, int Ligne)
{
    int x,y;
    for(y = Ligne; y > 3; y--)
	{
		for(x = 1; x < getDimX(jeu.terrain)-2; x++)
		{
			jeu.terrain.tableauPiecesPosees[y][x] = jeu.terrain.tableauPiecesPosees[y-1][x];
		}
	}
	//la premiere ligne affichée contient que des zeros
	for(x = 1; x < getDimX(jeu.terrain)-2; x++)
	{
	    jeu.terrain.tableauPiecesPosees[4][x] = '0';
	}
}

void LigneComplete(plateauDeJeu & jeu)
{
    int y;
    int compteur = 0;
    for(y = getDimY(jeu.terrain)-3; y > 3; y--)
    {
        while (estLigneComplete(jeu, y))   //si la ligne y est complete
        {
            effacerLigne(jeu, y);       //on efface la ligne dans le tableauPiecesPosees et on change le tableau
            compteur++;                 // on compte le nombre de lignes effacées
        }
    }
    //on verifie si il y a un tetris et on modifie la structure score
    if (compteur == 4) //on a un tetris (augmente le score de 60)
    {
        SetScore(jeu.Score, GetScore(jeu.Score) + 60);
    }
    else //pas de tetris
    {
        SetScore(jeu.Score, GetScore(jeu.Score) + compteur*10);
    }
    SetNbreLigne(jeu.Score, GetNbreLigne(jeu.Score)+compteur); // on incremente le nombre de ligne
    if(GetNbreLigne(jeu.Score) >= 10*(GetNiveau(jeu.Score)+1))
    {
            SetNiveau(jeu.Score,GetNiveau(jeu.Score)+1);
    }
}
